package xyz.zyl2020.security.config;

import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import xyz.zyl2020.security.dao.UserDao;
import xyz.zyl2020.security.entity.Role;

import javax.annotation.Resource;

/**
 * Security配置类
 *
 * @author ZhuYinglong
 * @date 2020/8/19 0019
 */
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private UserDao userDao;

    /**
     * 配置请求授权规则
     *
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/css/**", "/", "/index", "/loginPage").permitAll() // 无需认证
                .anyRequest().authenticated() // 其他请求都需要认证
        ;

        http.formLogin() // 开启登录，如果没有权限，就会跳转到登录页
                .loginPage("/loginPage") // 自定义登录页，默认/login（get请求）
                .loginProcessingUrl("/login") // 登录处理地址，默认/login（post请求）
                .usernameParameter("inputEmail") // 自定义username属性名，默认username
                .passwordParameter("inputPassword") // 自定义password属性名，默认password
        ;

        http.rememberMe() // 开启记住我
                .rememberMeParameter("rememberMe") // 自定义rememberMe属性名
        ;

        http.logout() // 开启注销
                .logoutUrl("/logout") // 注销处理路径，默认/logout
                .logoutSuccessUrl("/") // 注销成功后跳转路径
        ;

        http.csrf().disable(); // 禁止csrf
    }

    /**
     * 鉴权
     *
     * @return
     */
    @Bean
    public UserDetailsService userDetailsService() throws UsernameNotFoundException{
        return username -> {
            xyz.zyl2020.security.entity.User user = userDao.findByUsernameOrEmail(username, username);
            if (user == null) {
                throw new UsernameNotFoundException("账号或密码错误！");
            }
            String[] roleCodeArray = user.getRoles().stream().map(Role::getCode).toArray(String[]::new);

            return User.withUsername(user.getUsername())
                    .password(user.getPassword())
                    .roles(roleCodeArray)
                    .build();
        };
    }

    /**
     * 配置密码编码格式
     *
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
